package com.gxa.ticket.service.impl;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.gxa.ticket.dao.CityDao;
import entity.*;

import com.gxa.ticket.param.FlightParam;
import dto.ResultDTO;
import com.gxa.ticket.dao.AirlineDao;
import com.gxa.ticket.dao.FlightDao;
import com.gxa.ticket.validator.MyValidator;
import dto.ResultDTO;
import com.gxa.ticket.dao.FlightDao;
import com.gxa.ticket.service.FlightService;

import exception.SystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import util.Response;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 航班表(Flight)表服务实现类
 *
 * @author makejava
 * @since 2021-05-10 18:44:34
 */
@Service("flightService")
public class FlightServiceImpl implements FlightService {
    @Resource
    private FlightDao flightDao;
    @Resource(name = "objectRedisTemplate")
    private RedisTemplate<String, Object> objectRedisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private AirlineDao airlineDao;
    @Resource
    private MyValidator validator;

    @Resource
    private CityDao cityDao;
    /**
     * 通过ID查询单条数据
     *
     * @param flightId 主键
     * @return 实例对象
     */
    @Override
    public Flight queryById(Integer flightId) {
        return this.flightDao.queryById(flightId);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<Flight> queryAllByLimit(int offset, int limit) {
        return this.flightDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param flight 实例对象
     * @return 实例对象
     */
    @Override
    public Flight insert(Flight flight) {
        this.flightDao.insert(flight);
        return flight;
    }

    /**
     * 修改数据
     *
     * @param flight 实例对象
     * @return 实例对象
     */
    @Override
    public Flight update(Flight flight) {
        this.flightDao.update(flight);
        return this.queryById(flight.getFlightId());
    }

    /**
     * 通过主键删除数据
     *
     * @param flightId 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer flightId) {
        return this.flightDao.deleteById(flightId) > 0;
    }

    /**
     * 搜素航班
     * @param flightParam
     * @return
     */
    @Override
    public ResultDTO findByCondition(FlightParam flightParam) {
        System.out.println(flightParam);
        if (flightParam.getStartCity() == null) {
            throw new SystemException(1001,"请输入出发城市");
        }
        if (flightParam.getEndCity() == null) {
            throw new SystemException(1001,"请输入到达城市城市");
        }
        Integer timesId = flightParam.getTimesId();
        String startDay = flightParam.getStartDay();



        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        String format = df.format(timestamp);
        if (!format.equals(startDay)) {
            if (startDay!= null) {
                String startDay1 = startDay + " 00:00:00";
                String startDay2 = startDay + " 23:59:59";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }
        }else {
            SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Timestamp timestamp1 = new Timestamp(System.currentTimeMillis());
            String startDay1 = df1.format(timestamp1);
            String startDay2 = startDay + " 23:59:59";
            flightParam.setStartDay1(startDay1);
            flightParam.setStartDay2(startDay2);
        }

        if (timesId != null && startDay!= null) {
            //写时间逻辑
            if (timesId == 1) {
                String startDay1 = startDay + " 00:00:00";
                String startDay2 = startDay + " 06:00:00";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }else if(timesId == 2){
                String startDay1 = startDay + " 06:00:00";
                String startDay2 = startDay + " 12:00:00";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }else if(timesId == 3){
                String startDay1 = startDay + " 12:00:00";
                String startDay2 = startDay + " 18:00:00";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }else if(timesId == 4){
                String startDay1 = startDay + " 18:00:00";
                String startDay2 = startDay + " 23:59:59";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }else {
//                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                Timestamp timestamp = new Timestamp(System.currentTimeMillis());
//                String startDay1 = df.format(timestamp);
//                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
//                Timestamp timestamp = new Timestamp(System.currentTimeMillis());
//                String format = df.format(timestamp);
                //判断是不是当前日期,是当天就从当前时间开始到最后  不是就会查询一天的
//                if (format.endsWith(startDay)) {
//
//                }

                String startDay1 = startDay + " 00:00:00";
                String startDay2 = startDay + " 23:59:59";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }
        }
        Integer priceId = flightParam.getPriceId();
        if (priceId != null) {
            if (priceId == 1) {
                flightParam.setPrice1(0.0);
                flightParam.setPrice2(1111.0);
            }else if(priceId == 2){
                flightParam.setPrice1(1111.0);
                flightParam.setPrice2(2222.0);
            }else if(priceId == 3){
                flightParam.setPrice1(2222.0);
                flightParam.setPrice2(3333.0);
            }else if(priceId == 4){
                flightParam.setPrice1(3333.0);
                flightParam.setPrice2(9999.0);
            }else{
                throw new SystemException(1001,"价格错误");
            }
        }

        String endDay = flightParam.getEndDay();

        if (endDay != null) {
            String startDay1 = endDay + " 00:00:00";
            String startDay2 = endDay + " 23:59:59";
            flightParam.setStartDay1(startDay1);
            flightParam.setStartDay2(startDay2);
        }

        if (timesId != null && endDay != null) {
            //写时间逻辑
            if (timesId == 1) {
                String startDay1 = endDay + " 00:00:00";
                String startDay2 = endDay + " 06:00:00";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }else if(timesId == 2){
                String startDay1 = endDay + " 06:00:00";
                String startDay2 = endDay + " 12:00:00";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }else if(timesId == 3){
                String startDay1 = endDay + " 12:00:00";
                String startDay2 = endDay + " 18:00:00";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }else if(timesId == 4){
                String startDay1 = endDay + " 18:00:00";
                String startDay2 = endDay + " 23:59:59";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }else if(timesId == null){
                String startDay1 = endDay + " 00:00:00";
                String startDay2 = endDay + " 23:59:59";
                flightParam.setStartDay1(startDay1);
                flightParam.setStartDay2(startDay2);
            }
        }
        //分页
        PageHelper.startPage(flightParam.getPage(),flightParam.getPageSize());
        List<Flight> flightList = flightDao.findByCondition(flightParam);
        if (flightList == null) {
            throw new SystemException(1001,"没有数据");
        }
        //有多少条数据  分页
        int count = flightList.size();
//        //分页
//        PageHelper.startPage(flightParam.getPage(),flightParam.getPageSize());
        PageInfo<Flight> flightPageInfo = new PageInfo<>(flightList);

        // 存到Redis
        if (!stringRedisTemplate.hasKey("travel:total_time_asc")) {
            //进行删除操作
            stringRedisTemplate.delete("travel:total_time_asc");
        }
        if (!objectRedisTemplate.hasKey("travel:list")) {
            //进行删除操作
            stringRedisTemplate.delete("travel:list");
        }
        if (!objectRedisTemplate.hasKey("travel:price")) {
            //进行删除操作
            stringRedisTemplate.delete("travel:price");
        }
        if (!objectRedisTemplate.hasKey("travel:flight_end_time")) {
            //进行删除操作
            stringRedisTemplate.delete("travel:flight_end_time");
        }
        if (!objectRedisTemplate.hasKey("travel:flight_start_time")) {
            //进行删除操作
            stringRedisTemplate.delete("travel:flight_start_time");
        }

        Map<String, Flight> flightMap = new HashMap<>(16);
        for (Flight flight : flightList) {
            flightMap.put(flight.getFlightId().toString(),flight);
            //飞行时间
            stringRedisTemplate.opsForZSet().add("travel:total_time_asc",flight.getFlightId().toString(),flight.getFlightFlyTime());
            //价格
            stringRedisTemplate.opsForZSet().add("travel:price",flight.getFlightId().toString(),flight.getFlightMoney());
            //降落时间
            Timestamp flightEndTime = flight.getFlightEndTime();
            long time = flightEndTime.getTime();
            stringRedisTemplate.opsForZSet().add("travel:flight_end_time",flight.getFlightId().toString(),time);
            //起飞时间
            Timestamp flightStartTime = flight.getFlightStartTime();
            long time1 = flightStartTime.getTime();
            stringRedisTemplate.opsForZSet().add("travel:flight_start_time",flight.getFlightId().toString(),time1);

        }
        objectRedisTemplate.opsForHash().putAll("travel:list", flightMap);

        return new ResultDTO(200,"success",count,flightPageInfo);
    }

    /**
     * 查询机票是否存在
     * @param flightId :id
     * @return
     */
    @Override
    public ResultDTO findByFlightId(Integer flightId) {
        Flight flight = flightDao.queryById(flightId);
        if (flight == null) {
            return new ResultDTO(1001,"该航班不存在");
        }
        return new ResultDTO(200,"success",flight);
    }

    /**
     * 根据机票id 查询库存是否 >0 ,大于就减1
     * @param flightId：机票id
     * @return
     */
    @Override
    public ResultDTO selectCount(Integer flightId) {
        Flight flight = flightDao.queryById(flightId);
        Integer fightCount = flight.getFightCount();
        if (fightCount <= 0) {
            return new ResultDTO(1001,"没有座位了");
        }
        //减库存
        int count = flightDao.updateCount(flightId);
        if (count <= 0) {
            throw new SystemException(1001,"减库存失败");
        }
        return new ResultDTO(200,"success","2");
    }

    @Override
    public ResultDTO findByFlightId(List<MacOrder> orderList) {
        for (MacOrder macOrder : orderList) {
            List<OrderFight> orderFights = macOrder.getOrderFights();
            for (OrderFight orderFight : orderFights) {
                //得到机票id
                Integer flightId = orderFight.getFightId();
                Flight flight = flightDao.queryById(flightId);
                if (flight == null) {
                    return new ResultDTO(1001,"该航班不存在");
                }
//                //座位数
//                Integer fightCount = flight.getFightCount();
//                if (fightCount <= 0) {
//                    return new ResultDTO(1001,"没有座位了");
//                }
//                //减库存
//                int count = flightDao.updateCount(flightId);
//                if (count <= 0) {
//                    throw new SystemException(1001,"减库存失败");
//                }
//                Flight flight1 = flightDao.queryById(flightId);
                orderFight.setFlight(flight);
            }
        }

        return new ResultDTO(200,"success",orderList);
    }

    @Override
    public ResultDTO findAllAirline() {
        //在redis中查询
        if (!objectRedisTemplate.hasKey("travel:airline")) {
            //从数据库查询
            List<Airline> all = airlineDao.findAll();
            //存入redis
            objectRedisTemplate.opsForList().leftPushAll("travel:airline", all);
            //返回数据
            return Response.success(all);
        }
        //从redis
        List<Object> range = objectRedisTemplate.opsForList().range("travel:airline", 0, -1);
        return Response.success(range);
    }

    /**
     * 查询所有航空公司
     * @param airportIds
     * @return
     */
    @Override
    public ResultDTO findByAirport(Integer[] airportIds) {
        if (airportIds == null) {
            throw new SystemException(1001, "获取数据失败");
        }
        List<String> flightIds = new ArrayList<>();
        for (Integer airportId : airportIds) {
            String key = "travel:airport:" + airportId;
            if (!stringRedisTemplate.hasKey(key)) {
                continue;
            }
            Set<String> flightSet = stringRedisTemplate.opsForSet().members(key);
            flightIds.addAll(flightSet);
        }
        List<Object> flightList = objectRedisTemplate.opsForHash().multiGet("travel:flight:list", new ArrayList<>(flightIds));
        return Response.success(flightList);
    }

    @Override
    public ResultDTO findByStartTime(Integer[] timeIds) {
        if (timeIds == null) {
            throw new SystemException(1001, "数据获取失败");
        }
        List<String> flightIds = new ArrayList<>();
        for (Integer timeId : timeIds) {
            String key = "travel:start-time:"+timeId;
            if (!stringRedisTemplate.hasKey(key)) {
                continue;
            }
            Set<String> timeSet = stringRedisTemplate.opsForSet().members(key);
            flightIds.addAll(timeSet);
        }
        List<Object> flightList = objectRedisTemplate.opsForHash().multiGet("travel:flight:list", new ArrayList<>(flightIds));
        return Response.success(flightList);
    }

    @Override
    public ResultDTO startTimeAsc(FlightParam flightParam) {
        if (stringRedisTemplate.hasKey("travel:flight_start_time")) {
            Set<String> flightIds = stringRedisTemplate.opsForZSet().range("travel:flight_start_time", (flightParam.getPage()-1)*flightParam.getPageSize(), flightParam.getPage()*flightParam.getPageSize()-1);
            System.out.println(flightIds);
            //返回数据
            List<Object> flights= objectRedisTemplate.opsForHash().multiGet("travel:list", new ArrayList<>(flightIds));
            return Response.success(flights);
        }
        return Response.error(1001, "操作失败，请重新查询");
    }

    @Override
    public ResultDTO startTimeDesc(FlightParam flightParam) {
        if (!stringRedisTemplate.hasKey("travel:flight_start_time")) {
            return Response.error(1001, "操作失败，请重新查询");
        }
        Set<String> flightIds = stringRedisTemplate.opsForZSet().reverseRange("travel:flight_start_time", (flightParam.getPage()-1)*flightParam.getPageSize(), flightParam.getPage()*flightParam.getPageSize()-1);
        //返回数据
        List<Object> flights= objectRedisTemplate.opsForHash().multiGet("travel:list", new ArrayList<>(flightIds));
        return Response.success(flights);
    }

    @Override
    public ResultDTO endTimeAsc(FlightParam flightParam) {

        if (!stringRedisTemplate.hasKey("travel:flight_end_time")) {
            return Response.error(1001, "操作失败，请重新查询");
        }
        Set<String> flightIds = stringRedisTemplate.opsForZSet().range("travel:flight_end_time", (flightParam.getPage()-1)*flightParam.getPageSize(), flightParam.getPage()*flightParam.getPageSize()-1);

        //返回数据
        List<Object> flights= objectRedisTemplate.opsForHash().multiGet("travel:list", new ArrayList<>(flightIds));
        return Response.success(flights);
    }

    @Override
    public ResultDTO endTimeDesc(FlightParam flightParam) {
        if (!stringRedisTemplate.hasKey("travel:flight_end_time")) {
            return Response.error(1001, "操作失败，请重新查询");
        }
        Set<String> flightIds = stringRedisTemplate.opsForZSet().reverseRange("travel:flight_end_time", (flightParam.getPage()-1)*flightParam.getPageSize(), flightParam.getPage()*flightParam.getPageSize()-1);
        //返回数据
        List<Object> flights= objectRedisTemplate.opsForHash().multiGet("travel:list", new ArrayList<>(flightIds));
        return Response.success(flights);
    }

    @Override
    public ResultDTO totalTimeAsc(FlightParam flightParam) {
        if (!stringRedisTemplate.hasKey("travel:total_time_asc")) {
            return Response.error(1001, "操作失败，请重新查询");
        }
        //分页没写0 -1应为(paramVo.getPage() - 1) * paramVo.getPageSize(), paramVo.getPage() * paramVo.getPageSize() - 1
        Set<String> flightIds = stringRedisTemplate.opsForZSet().range("travel:total_time_asc", (flightParam.getPage()-1)*flightParam.getPageSize(), flightParam.getPage()*flightParam.getPageSize()-1);

        List<Object> flights= objectRedisTemplate.opsForHash().multiGet("travel:list", new ArrayList<>(flightIds));

        return new ResultDTO(200,"success",flights);
    }

    /**
     * 航班时长的降序
     * @param flightParam
     * @return
     */
    @Override
    public ResultDTO totalTimeDesc(FlightParam flightParam) {
        if (!stringRedisTemplate.hasKey("travel:total_time_asc")) {
            return Response.error(1001, "操作失败，请重新查询");
        }
        //分页没写0 -1应为(paramVo.getPage() - 1) * paramVo.getPageSize(), paramVo.getPage() * paramVo.getPageSize() - 1
        Set<String> flightIds = stringRedisTemplate.opsForZSet().reverseRange("travel:total_time_asc", (flightParam.getPage()-1)*flightParam.getPageSize(), flightParam.getPage()*flightParam.getPageSize()-1);

        List<Object> flights= objectRedisTemplate.opsForHash().multiGet("travel:list", new ArrayList<>(flightIds));

        return new ResultDTO(200,"success",flights);
    }

    /**
     * 价格升序
     * @return
     */
    @Override
    public ResultDTO priceAsc(FlightParam flightParam) {
        if (!stringRedisTemplate.hasKey("travel:price")) {
            return Response.error(1001, "操作失败，请重新查询");
        }
        Set<String> flightIds = stringRedisTemplate.opsForZSet().range("travel:price", (flightParam.getPage()-1)*flightParam.getPageSize(), flightParam.getPage()*flightParam.getPageSize()-1);
        List<Object> flights= objectRedisTemplate.opsForHash().multiGet("travel:list", new ArrayList<>(flightIds));
        return new ResultDTO(200,"success",flights);
    }

    /**
     * 价格降序
     * @return
     */
    @Override
    public ResultDTO priceDesc(FlightParam flightParam) {
        if (!stringRedisTemplate.hasKey("travel:price")) {
            return Response.error(1001, "操作失败，请重新查询");
        }
        Set<String> flightIds = stringRedisTemplate.opsForZSet().reverseRange("travel:price", (flightParam.getPage()-1)*flightParam.getPageSize(), flightParam.getPage()*flightParam.getPageSize()-1);
        List<Object> flights= objectRedisTemplate.opsForHash().multiGet("travel:list", new ArrayList<>(flightIds));
        return new ResultDTO(200,"success",flights);
    }

    @Override
    public ResultDTO findCity() {
        List<City> cityList = cityDao.findAll();
        return new ResultDTO(200,"success",cityList);
    }

    @Override
    public ResultDTO findAllFlight() {
        List<Flight> allFlight = flightDao.findAllFlight();
        return new ResultDTO(200,"success",allFlight);
    }

    @Override
    public ResultDTO findFlightList(Integer[] flightIds) {
        List<Flight> flightList = new ArrayList<>();
        for (Integer flightId : flightIds) {
            Flight flight = flightDao.queryById(flightId);
            flightList.add(flight);
        }
        return new ResultDTO(200,"success",flightList);
    }
}
